package ru.susu.algebra.util;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import ru.susu.algebra.pair.Pair;

/**
 * @author akargapolov
 * @since: 05.05.2010
 */
public class ArrayMap<K, V> extends AbstractMap<K, V>
{
	private ArrayList<K> _keys = new ArrayList<K>();
	private ArrayList<V> _values = new ArrayList<V>();

	private Map<K, Integer> _index = null;

	public ArrayList<K> getKeys()
	{
		return _keys;
	}

	public ArrayList<V> getValues()
	{
		return _values;
	}

	@Override
	public int size()
	{
		return _keys.size();
	}

	public void trimToSize()
	{
		_keys.trimToSize();
		_values.trimToSize();
	}

	@Override
	public V put(K key, V value)
	{
		ensureIndexInitilized();
		Integer index = _index.get(key);
		if (index == null)
		{
			_keys.add(key);
			_values.add(value);
			index = _values.size() - 1;
			_index.put(key, index);
		}
		else
		{
			_keys.set(index, key);
			_values.set(index, value);
		}
		return _values.get(index);
	}

	@Override
	public boolean containsKey(Object key)
	{
		return null != get(key);
	}

	@Override
	public V get(Object key)
	{
		ensureIndexInitilized();
		Integer index = _index.get(key);
		return index == null ? null : _values.get(index);
	}

	protected void ensureIndexInitilized()
	{
		if (_index == null)
		{
			_index = new HashMap<K, Integer>();
			for (int index = 0; index < _keys.size(); index++)
			{
				_index.put(_keys.get(index), index);
			}
		}
	}

	public void dropIndex()
	{
		_index = null;
	}

	@Override
	public Set<Map.Entry<K, V>> entrySet()
	{
		Set<Map.Entry<K, V>> result = new HashSet<Map.Entry<K, V>>();
		for (int index = 0; index < _keys.size(); index++)
		{
			Pair<K, V> pair = new Pair<K, V>(_keys.get(index), _values.get(index));
			result.add(pair);
		}
		return result;
	}

	@Override
	public void clear()
	{
		_keys = new ArrayList<K>();
		_values = new ArrayList<V>();
		_index = null;
	}

}
